/**
 * Project2Frame.java
 * Part of the Particle Physics Simulator
 * By Wilson Burhan and Tyler Simrell
 * Version 1.0
 * Date Finished: 5/8/13
 */

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Hashtable;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * This class is the frame that envelopes the ParticleCanvas and gives the user
 * control over the forces.
 * @author Tyler Simrell and Wilson Burhan
 *
 */
public class Project2Frame 
{
	/**
	 * The minimum Coefficient of Restitution value.
	 */
	private static final int MIN_COR = 0;
	
	/**
	 * The maximum Coefficient of Restitution value. The reason
	 * why there is a max is because if it goes beyond 1, it 
	 * will lead to bad behavior. It tops out at 10 because
	 * it is work around for the fact that the slider only 
	 * takes ints, not floats or doubles. 
	 */
	private static final int MAX_COR = 10;
	
	private JFrame frame;
	private ParticleCanvas canvas;
	private JPanel mainPanel;
	private JSlider corSlider;
	private JButton windButton;
	private JButton gravityButton;
	private JCheckBox isVectorField;
	private JCheckBox collision;
	
	/**
	 * This method sets up the frame for being ran.
	 */
	private void setUp()
	{
		frame = new JFrame("Project 2 - Particle Simulator");
		isVectorField = new JCheckBox("Vector Field");
		collision = new JCheckBox("Particle Collision");
		mainPanel = new JPanel(new BorderLayout());
		frame.add(mainPanel);
		canvas = new ParticleCanvas();
		createButtons();
		createSliderAndCheckbox();
		
		mainPanel.add(canvas);
		frame.setSize(500, 500);
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
		canvas.requestFocus();
		frame.pack();
	}
	
	/**
	 * This method creates the buttons on the top of the screen.
	 */
	private void createButtons() 
	{
		gravityButton = new JButton("Turn Gravity Off");
		//button2 & button3 don't do anything for now.
		windButton = new JButton("Turn Wind On");
		final JButton singularityButton = new JButton("Turn On Singularity");
		final JButton restartButton = new JButton("Restart");
		
		gravityButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) 
			{
				boolean gravityState = canvas.toggleGravity();
				if(gravityState)
				{
					gravityButton.setText("Turn Gravity Off");
				}
				else
				{
					gravityButton.setText("Turn Gravity On");
				}
				canvas.requestFocus();
			}
		});
		
		windButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				boolean isWindy = canvas.toggleWind();
				if(isWindy)
					windButton.setText("Turn Off wind");
				else
					windButton.setText("Turn On wind");
				
				canvas.requestFocus();
			}
		});
		
		singularityButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent e) 
			{
				boolean isSingularity = canvas.toggleSingularity();
				if(isSingularity)
				{
					singularityButton.setText("Big Bang");
					gravityButton.setText("Turn On Gravity");
					gravityButton.setEnabled(false);
					windButton.setText("Turn On Wind");
					windButton.setEnabled(false);
				}
				else
				{
					singularityButton.setText("Turn On Singularity");
					gravityButton.setEnabled(true);
					windButton.setEnabled(true);
				}
				canvas.requestFocus();
			}
		});
		
		restartButton.addActionListener(new ActionListener(){
			@Override
			public void actionPerformed(ActionEvent event)
			{
				mainPanel.remove(canvas);
				canvas = new ParticleCanvas();
				mainPanel.add(canvas);
				windButton.setText("Turn On Wind");
				gravityButton.setText("Turn Off Gravity");
				mainPanel.revalidate();
				isVectorField.setSelected(false);
				canvas.requestFocus();
			}
		});
		
		JPanel buttonPanel = new JPanel();
		buttonPanel.add(gravityButton);
		buttonPanel.add(windButton);
		buttonPanel.add(singularityButton);
		buttonPanel.add(restartButton);
		frame.add(buttonPanel, BorderLayout.NORTH);
	}
	
	/**
	 * This method creates the slider for the Coefficient of Restitution
	 * and check box that toggles the vector field on and off on the bottom
	 * of the screen.
	 */
	private void createSliderAndCheckbox()
	{
		JPanel bottomPanel = new JPanel(new GridLayout(2,1));
		JPanel sliderPanel = new JPanel(new BorderLayout());
		JLabel title = new JLabel("Coefficient of Restitution", JLabel.CENTER);
		title.setAlignmentX(Component.CENTER_ALIGNMENT);
		sliderPanel.add(title, BorderLayout.NORTH);
		
		JPanel checkboxPanel = new JPanel();
		isVectorField.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if(isVectorField.isSelected()) {
					canvas.isVectorField = true;
					canvas.toggleVectorField();
				}
				else {
					canvas.isVectorField = false;
					canvas.toggleVectorField();
				}
			}
		});
		collision.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(collision.isSelected()) {
					canvas.toggleCollision = true;
				}
				else {
					canvas.toggleCollision = false;
				}
			}
		});
		
		checkboxPanel.add(isVectorField);
		checkboxPanel.add(collision);
		
		corSlider = new JSlider(MIN_COR, MAX_COR, 10); // cor = Coefficient of Restitution
		corSlider.setMajorTickSpacing(25);
		Hashtable<Integer, JLabel> decimalNumbers = new Hashtable<Integer, JLabel>();
		
		decimalNumbers.put(new Integer(0), new JLabel("0")); //May as well attempt to
		decimalNumbers.put(new Integer(1), new JLabel(".1"));//save some CPU cycles
		decimalNumbers.put(new Integer(2), new JLabel(".2"));//by not making Java do
		decimalNumbers.put(new Integer(3), new JLabel(".3"));//"boxing and unboxing" here
		decimalNumbers.put(new Integer(4), new JLabel(".4"));
		decimalNumbers.put(new Integer(5), new JLabel(".5"));
		decimalNumbers.put(new Integer(6), new JLabel(".6"));
		decimalNumbers.put(new Integer(7), new JLabel(".7"));
		decimalNumbers.put(new Integer(8), new JLabel(".8"));
		decimalNumbers.put(new Integer(9), new JLabel(".9"));
		decimalNumbers.put(new Integer(10), new JLabel("1.0"));
		corSlider.setLabelTable(decimalNumbers);
		
		corSlider.setPaintLabels(true);
		corSlider.setPaintTicks(true);
		corSlider.addChangeListener(new ChangeListener() {
			
			@Override
			public void stateChanged(ChangeEvent event) 
			{
				JSlider source = (JSlider) event.getSource();
				if(!source.getValueIsAdjusting())
				{
					canvas.setCoefficientOfRestitution(((float)source.getValue())/10);
				}
			}
		});
		sliderPanel.add(corSlider);
		bottomPanel.add(checkboxPanel);
		bottomPanel.add(sliderPanel);
		mainPanel.add(bottomPanel, BorderLayout.SOUTH);
	}
	
	public static void main(String[] args) 
	{
		javax.swing.SwingUtilities.invokeLater(new Runnable() 
		{
            public void run() 
            {
                new Project2Frame().setUp();
            }
        });
	}

}
